<template>
  <div class="app-container">
    <el-row>
      <el-col :span="24">
        <el-button class="margin-right" type="text" icon="el-icon-refresh" @click="loadGroupAndRepos" />

        <el-select style="width: 250px" size="small" :value="repositoryChoseShow" @change="loadBranchs">
          <el-option-group
            v-for="item in groupAndRepos"
            :key="item.group"
            :label="item.group"
          >
            <el-option
              v-for="repository in item.repositorys"
              :key="repository"
              :label="repository"
              :value="repository+'$'+item.group"
            />
          </el-option-group>
        </el-select>

        <el-button size="small" @click="addUrlDialog.show = true">新建仓库</el-button>

        <el-tag type="info" class="margin-left margin-right"><b>当前分支: </b><span>{{ currentBranchName }}</span></el-tag>
        <el-button :disabled="!input.repository" size="small" class="margin-right" icon="el-icon-download" @click="pull">pull</el-button>

        <el-select v-model="currentBranchName" filterable style="width: 250px" size="small" @change="switchBranch">
          <el-option v-for="branch in branchs" :key="branch.branchName" :label="branch.branchName" :value="branch.branchName" />
        </el-select>

        <el-checkbox v-model="lock.force" class="margin-left " :disabled="!lock.state">强制</el-checkbox>
        <el-button type="primary" class="margin-left" size="small" @click="lockRepository">{{ lock.title }}</el-button>
      </el-col>
    </el-row>

    <el-row>
      <el-col :span="15">
        <!--        <p><b>创建补丁:</b> 创建的补丁包时,当有多个提交记录被选择的时候,只会取第一个和最后一个提交记录比较差异  </p>-->
        <!--        <el-button type="primary" class="margin-bottom" size="small" :disabled="!input.group || !input.repository || experimental" @click="createPatch">创建补丁</el-button>-->
        <!--        <el-checkbox v-model="experimental" class="margin-left margin-right">允许实验功能(创建多提交记录补丁)</el-checkbox>-->
        <el-button-group class="margin-top">
          <el-button v-loading.fullscreen.lock="fullscreenLoading" type="primary" class="margin-bottom margin-left" size="small" :disabled="!input.group || !input.repository || !experimental" @click="createPatchMultiCommit">创建多提交记录补丁</el-button>
          <el-button size="small" type="default" @click="loadHistory">补丁历史</el-button>
          <el-button size="small" type="default" @click="guessCompileModules">编译模块猜测</el-button>
        </el-button-group>

        <el-table
          ref="commitTable"
          v-loading="tableLoad"
          :data="commits"
          border
          stripe
          height="500"
          row-key="commitId"
          size="mini"
        >
          <el-table-column
            type="index"
            width="50"
          />
          <el-table-column
            :selectable="checkSelect"
            type="selection"
            width="55"
          />
          <el-table-column
            prop="author"
            label="作者"
            width="180"
          />
          <el-table-column
            prop="message"
            label="提交信息"
          />
          <el-table-column
            prop="time"
            label="提交时间"
            width="150"
          />
          <el-table-column
            fixed="right"
            label="操作"
            width="100"
          >
            <template slot-scope="scope">
              <el-button type="text" size="small" :disabled="scope.row.commitId === commits[0].commitId" @click="switchBranch(scope.row.commitId)">切换</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-col>
      <el-col :span="9">
        <div class="panel panel-default">
          <div class="panel-heading" style="padding: 2px 15px;">
            <span class="margin-right" >模块列表</span>
            <el-button size="small" type="text" icon="el-icon-refresh" @click="loadPomFiles">刷新</el-button>
          </div>
          <div class="panel-body" style="height: 80vh;overflow-y: scroll">
            <el-tree
              v-loading="moduleTree.loading"
              :props="moduleTree.treeProps"
              :data="moduleTree.data"
              :default-expand-all="true"
              :highlight-current="true"
            >
              <div slot-scope="{ node, data }" :title="data.relativePath" class="custom-tree-node">
                <b>{{ data.moduleName }}</b>
                <span class="margin-left">{{ data.lastCompileTime || '未编译' }}</span>
                <div>
                  <el-button type="text" size="mini" @click="mvnCommand('clean compile',data.relativePath)">编译</el-button>
                  <el-button type="text" size="mini" @click="mvnCommand('clean install',data.relativePath)">安装</el-button>
                </div>
              </div>
            </el-tree>
          </div>
        </div>

        <!--        <el-table-->
        <!--          :data="pomFiles"-->
        <!--          border-->
        <!--          stripe-->
        <!--          ref="pomTable"-->
        <!--          v-loading="compileLoad"-->
        <!--          height="500"-->
        <!--          size="mini">-->
        <!--          <el-table-column-->
        <!--            type="index"-->
        <!--            width="50"/>-->
        <!--          <el-table-column-->
        <!--            prop="moduleName"-->
        <!--            label="模块名"-->
        <!--            width="180"/>-->
        <!--          <el-table-column-->
        <!--            prop="relativePath"-->
        <!--            label="路径"/>-->
        <!--          <el-table-column-->
        <!--            fixed="right"-->
        <!--            label="操作"-->
        <!--            width="100">-->
        <!--            <template slot-scope="scope">-->
        <!--              <el-button type="text" size="small" @click="compile(scope.row)">编译</el-button>-->
        <!--            </template>-->
        <!--          </el-table-column>-->
        <!--        </el-table>-->
      </el-col>
    </el-row>

    <!-- 编译结果 -->
    <el-dialog fullscreen :visible.sync="compileResultDialog.show" title="编译结果" @close="closeDialog">
      <pre ref="output" style="overflow-y: scroll;height: 87vh">{{ compileResultDialog.message }}</pre>
    </el-dialog>

    <!-- 添加仓库 -->
    <el-dialog v-loading="addUrlDialog.loading" :visible.sync="addUrlDialog.show" title="添加克隆">
      <el-form ref="addUrlDialogForm" :model="addUrlDialog.input" size="small" label-width="80px" :rules="addUrlDialog.rules">
        <el-form-item label="分组" prop="group">
          <el-select v-model="addUrlDialog.input.group">
            <el-option v-for="group in addUrlDialog.groups" :key="group" :label="group" :value="group" />
          </el-select>
        </el-form-item>
        <el-form-item label="地址" prop="url">
          <el-input v-model="addUrlDialog.input.url" placeholder="输入仓库地址" />
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button size="small" type="primary" @click="cloneRepository">添加</el-button>
      </span>
    </el-dialog>

    <!-- 编译文件预览 -->
    <el-dialog :title="changeFilesDialog.title" width="80%" :visible.sync="changeFilesDialog.show">
      <el-input v-model="input.title" style="margin-top: -10px;" size="small" placeholder="增量说明" />
      <div class="margin-bottom margin-top" style="">
        源文件数量 <b>{{ compileCount.originFiles }}</b> -> 编译后文件数量 <b>{{ compileCount.compileFiles }}</b>
        <span v-if="compileCount.errorFiles" :title="compileCount.errorFileIndexes.join(',')" class="margin-left text-danger" style="color: red">错误文件数量: {{ compileCount.errorFiles }}</span>
      </div>
      <el-table
        :data="changeFilesDialog.data != null ? changeFilesDialog.data.changeFiles : []"
        border
        stripe
        height="500"
        size="mini"
      >
        <el-table-column type="expand">
          <template slot-scope="props">
            <ul class="data-list">
              <li v-for="path in props.row.compileFiles" :key="path.path" style="overflow-x: scroll;white-space: nowrap;font-size: 12px;">
                <span>{{ formatTime(path.time) }}</span>
                <span class="margin-left">{{ path.path }}</span>
              </li>
            </ul>
          </template>
        </el-table-column>
        <el-table-column
          type="index"
          label="序号"
          width="55"
        />
        <el-table-column
          prop="changeType"
          label="变更类型"
          width="100"
        />
        <el-table-column
          prop="relativePath"
          label="路径"
        />
        <el-table-column
          label="编译文件数量"
          width="100"
        >
          <template slot-scope="scope">
            <span v-if="scope.row.compilePaths.length === 0 && scope.row.changeType !== 'DELETE'" class="text-danger" style="color: red">{{ scope.row.compilePaths.length }}</span>
            <span v-else class="">{{ scope.row.compilePaths.length }}</span>
          </template>
        </el-table-column>
      </el-table>

      <el-button class="margin-top" type="primary" size="small" @click="downloadPatch">下载补丁</el-button>
    </el-dialog>

    <!-- 历史补丁记录 -->
    <el-dialog :title="historyDialog.title" :visible.sync="historyDialog.show">
      <div class="margin-bottom" style="margin-top: -10px">
        历史补丁数量: <b>{{ historyDialog.patchs.length }}</b>

        <el-button class="margin-left" type="text" size="small" @click="cleanNotEffectHistoryPatch">清空无效记录</el-button>
      </div>

      <el-table
        :data="historyDialog.patchs"
        border
        stripe
        size="mini"
        :row-class-name="historyTableRowClass"
      >
        <el-table-column
          type="index"
          label="序号"
          width="55"
        />
        <el-table-column
          prop="title"
          label="增量说明"
        />
        <el-table-column
          prop="branch"
          label="分支"
          width="200"
        />
        <el-table-column
          prop="time"
          label="创建时间"
          width="180"
        >
          <template slot-scope="scope">
            <span>{{ parseTime(scope.row.time) }}</span>
          </template>

        </el-table-column>
        <el-table-column
          prop="user"
          label="添加增量人"
          width="100"
        />
        <el-table-column
          fixed="right"
          label="操作"
          width="150"
        >
          <template slot-scope="scope">
            <el-button type="text" :disabled="!scope.row.effect" size="small" @click="downloadHistoryPatch(scope.row.filePath,scope.row.title)">下载</el-button>
            <el-button type="text" size="small" @click="deleteHistoryPatch(scope.row.filePath)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>

    <!-- 猜测模块数据 -->
    <el-dialog :title="guessModuleTree.dialog.title" :visible.sync="guessModuleTree.dialog.show">
      <el-tree
        v-loading="guessModuleTree.loading"
        :props="guessModuleTree.treeProps"
        :data="guessModuleTree.data"
        :default-expand-all="true"
        :highlight-current="true"
      >
        <div slot-scope="{ node, data }" :title="data.relativePath" class="custom-tree-node">
          <b>{{ data.moduleName }}</b>
          <span class="margin-left">{{ data.lastCompileTime || '未编译' }}</span>
          <el-button type="text" size="mini" @click="mvnCommand('clean compile',data.relativePath)">编译</el-button>
        </div>
      </el-tree>
    </el-dialog>
  </div>
</template>

<script>
import git from '@/api/git'
import core from '@/api/core'

import { formatTime, parseTime } from '@/utils'

export default {
  name: 'gitOld',
  data() {
    return {
      lock: {
        state: true,
        title: '解锁',
        force: false
      },
      fullscreenLoading: false,
      groupAndRepos: [],
      currentBranchName: null,
      branchs: [],
      commits: [],
      tableLoad: false,
      compileLoad: false,
      pomFiles: [],
      experimental: true,
      input: {
        group: null,
        repository: null,
        commitBeforeId: null,
        commitAfterId: null,
        commitIds: [],
        title: null
      },
      switchBranchInput: {
        branchName: null
      },
      compileResultDialog: {
        show: false,
        message: '',
        subsrcibes: []
      },
      addUrlDialog: {
        loading: false,
        show: false,
        groups: [],
        input: {
          group: null,
          url: null
        },
        rules: {
          group: [{ required: true, trigger: 'blur', message: '分组必填' }],
          url: [{ required: true, trigger: 'blur', message: '仓库地址必填' }]
        }
      },
      changeFilesDialog: {
        show: false,
        data: null,
        title: '变更文件列表',
        patchMethod: null
      },
      moduleTree: {
        loading: false,
        treeProps: {
          children: 'childrens',
          label: 'moduleName'
        },
        data: []
      },
      guessModuleTree: {
        loading: false,
        treeProps: {
          children: 'childrens',
          label: 'moduleName'
        },
        data: [],
        dialog: {
          show: false,
          title: '猜测需要编译的模块'
        }
      },
      historyDialog: {
        show: false,
        patchs: [],
        title: '补丁历史记录'
      }
    }
  },
  computed: {
    repositoryChoseShow() {
      if (!this.input.group) {
        return '请先添加分组, 然后新建仓库'
      }
      return this.input.group + '->' + this.input.repository
    },
    compileCount() {
      if (this.changeFilesDialog.data && this.changeFilesDialog.data.changeFiles) {
        const originFiles = this.changeFilesDialog.data.changeFiles.length
        let compileFiles = 0; let errorFiles = 0; const errorFileIndexes = []
        for (let i = 0; i < this.changeFilesDialog.data.changeFiles.length; i++) {
          const changeFile = this.changeFilesDialog.data.changeFiles[i]
          compileFiles += changeFile.compilePaths.length

          if (changeFile.compilePaths.length === 0 && changeFile.changeType !== 'DELETE') {
            errorFiles++
            errorFileIndexes.push(i + 1)
          }
        }

        return { originFiles, compileFiles, errorFiles, errorFileIndexes }
      }
      return { originFiles: 0, compileFiles: 0, errorFiles: 0 }
    }
  },
  mounted() {
    this.loadGroupAndRepos()
    git.groups().then(res => {
      this.addUrlDialog.groups = res.data
    })
  },
  methods: {
    guessCompileModules() {
      const select = this.$refs['commitTable'].selection
      if (!select || select.length < 1) {
        this.$message('必须选中至少一个提交记录')
        return
      }

      this.input.commitIds = []
      for (let i = 0; i < select.length; i++) {
        this.input.commitIds.push(select[i].commitId)
      }

      git.guessCompileModules(this.input).then(res => {
        this.guessModuleTree.dialog.show = true;
        this.guessModuleTree.data = res.data;
      })
    },
    loadHistory() {
      this.historyDialog.title = '分组 [ ' + this.input.group + ' ] 仓库 [ ' + this.input.repository + ' ] 的历史补丁记录'
      git.historyPatch(this.input.group, this.input.repository).then(res => {
        this.historyDialog.patchs = res.data || []
        this.historyDialog.show = true
      })
    },
    downloadHistoryPatch(filepath, title) {
      this.historyDialog.show = false
      core.fileDownload(filepath, title + '.zip')
    },
    deleteHistoryPatch(filepath) {
      git.deleteHistoryPatch(filepath).then(res => {
        this.loadHistory()
      })
    },
    cleanNotEffectHistoryPatch() {
      git.cleanNotEffectHistoryPatch().then(res => {
        this.loadHistory()
      })
    },
    historyTableRowClass({ row, rowIndex }) {
      if (!row.effect) {
        return 'error-row'
      }
      return ''
    },
    formatTime, parseTime,
    lockRepository() {
      if (this.lock.state) {
        git.unLock(this.input.group, this.input.repository, this.lock.force).then(res => {
          this.lock.state = false
          this.lock.title = '锁定'
        })
      } else {
        git.lock(this.input.group, this.input.repository).then(res => {
          this.lock.state = true
          this.lock.title = '解锁'
        })
      }
    },
    checkSelect(row, index) {
      if (this.experimental) {
        return true
      }
      return index !== 0
    },
    cloneRepository() {
      this.$refs['addUrlDialogForm'].validate((valid) => {
        if (valid) {
          this.addUrlDialog.loading = true
          git.cloneRepository(this.addUrlDialog.input.group, this.addUrlDialog.input.url).then(res => {
            this.addUrlDialog.show = false
            this.loadGroupAndRepos()
            this.addUrlDialog.loading = false
          }).catch(res => {
            this.addUrlDialog.loading = false
          })
        }
      })
    },
    loadGroupAndRepos() {
      git.groupRepositorys().then(res => {
        this.groupAndRepos = res.data

        if (this.groupAndRepos && this.groupAndRepos.length > 0) {
          // 默认选择第一个分组和仓库
          this.loadBranchs({ group: this.groupAndRepos[0].group, repository: this.groupAndRepos[0].repositorys[0] })
        }
      })
    },
    loadBranchs(value) {
      if (typeof value === 'string') {
        this.input.group = value.split('$')[1]
        this.input.repository = value.split('$')[0]
      } else {
        this.input.group = value.group
        this.input.repository = value.repository
      }

      git.branchs(this.input.group, this.input.repository).then(res => {
        this.branchs = res.data.branches
        this.currentBranchName = res.data.currentBranchName

        this.loadCommits()
        this.loadPomFiles()
      })
    },
    loadCommits() {
      this.tableLoad = true
      git.commits(this.input.group, this.input.repository).then(res => {
        this.tableLoad = false
        this.commits = res.data
        if (this.commits && this.commits.length > 0 && !this.experimental) {
          // 默认选中第一行
          this.$nextTick(function() {
            this.$refs['commitTable'].toggleRowSelection(this.commits[0])
          })
        }
      }).catch(res => {
        this.tableLoad = false
      })
    },
    loadPomFiles() {
      // git.pomFiles(this.input.group,this.input.repository).then(res => {
      //   this.pomFiles = res.data;
      // })
      // 改为加载模块树
      this.moduleTree.loading = true
      git.modules(this.input.group, this.input.repository).then(res => {
        this.moduleTree.data = res.data
        this.moduleTree.loading = false
      }).catch(res => {
        this.moduleTree.loading = false
      })
    },
    mvnCommand(command,relativePath) {
      git.lock(this.input.group, this.input.repository).then(res => {
        this.compileResultDialog.message = ''
        this.compileResultDialog.show = true

        const websocketId = Math.round(Math.random() * 1000)
        let listenTopic = '/topic/'+this.input.group+'/'+this.input.repository+'/'+websocketId;
        this.compileResultDialog.subsrcibes.push(listenTopic)
        this.$websocket.dispatch('WEBSOCKET_SUBSRCIBE',{topic: listenTopic,callback:this.reviceMessage});

        let message = JSON.stringify({ websocketId: websocketId, group: this.input.group, repository: this.input.repository, relativePath: relativePath,mvnCommand: command });
        this.$websocket.dispatch('WEBSOCKET_SEND',{topic: '/app/execMavenCommand',data: message})
      })

      // git.compile(websocketId,this.input.group,this.input.repository,relativePath).then(res => {});
    },
    closeDialog() {
      if (this.compileResultDialog.subsrcibes){
        for (let i = 0; i < this.compileResultDialog.subsrcibes.length; i++) {
          let listenTopic = this.compileResultDialog.subsrcibes[i];
          this.$websocket.dispatch('WEBSOCKET_UNSUBSRCIBE',listenTopic);
        }
      }
      this.compileResultDialog.subsrcibes.length = 0 ;

    },
    reviceMessage(response) {
      const data = response.body
      this.compileResultDialog.message += data
      this.compileResultDialog.message += '\n'
      if (this.$refs.output){
        this.$refs.output.scrollTop = this.$refs.output.scrollHeight
      }

      // 如果编译成功, 重新加载模块列表
      if (parseInt(data.trim()) === 0){
        this.loadPomFiles()
      }
    },
    switchBranch(branchName) {
      git.lock(this.input.group, this.input.repository).then(res => {
        this.tableLoad = true
        git.switchBranch(this.input.group, this.input.repository, branchName).then(res => {
          this.tableLoad = false
          this.loadCommits()
          this.loadPomFiles()
        }).catch(res => {
          this.tableLoad = false
        })
      })
    },
    pull() {
      this.tableLoad = true
      git.pull(this.input.group, this.input.repository).then(res => {
        this.tableLoad = false
        this.loadBranchs({ group: this.input.group, repository: this.input.repository })
      })
    },
    downloadPatch() {
      this.changeFilesDialog.patchMethod.call(this, this.input).then(res => {
        core.fileDownload(res.data, this.input.title ? this.input.title + '.zip' : undefined)
      })
    },
    createPatch() {
      const select = this.$refs['commitTable'].selection
      if (!select || select.length < 2) {
        this.$message('第一个提交必须选中,然后还必须再选一个做对比')
        return
      }

      git.newCompileTime(this.input.group, this.input.repository).then(res => {
        if (res.data < new Date().getTime() - 3600000) {
          // 如果超过一小时没编译 , 提示用户编译
          this.$confirm('超过一小时(' + formatTime(res.data) + ')没有编译项目了,确定要创建补丁吗', '警告', { type: 'warning' }).then(() => {
            this.doCreatePatch(select)
          }).catch(() => {})
        } else {
          this.doCreatePatch(select)
        }
      })
    },
    doCreatePatch(select) {
      this.input.commitBeforeId = select[select.length - 1]['commitId']
      this.input.commitAfterId = select[0]['commitId']
      git.changeFiles(this.input).then(res => {
        this.changeFilesDialog.data = res.data
        this.changeFilesDialog.title = this.input.commitBeforeId + ' compare ' + this.input.commitAfterId
        this.changeFilesDialog.show = true
        this.changeFilesDialog.patchMethod = git.createPatch
      })
    },
    createPatchMultiCommit() {
      const select = this.$refs['commitTable'].selection
      if (!select || select.length < 1) {
        this.$message('必须选中至少一个提交记录')
        return
      }

      git.newCompileTime(this.input.group, this.input.repository).then(res => {
        if (res.data < new Date().getTime() - 3600000) {
          this.$confirm('超过一小时(' + formatTime(res.data) + ')没有编译项目了,确定要创建补丁吗', '警告', { type: 'warning' }).then(() => {
            this.doCreatePatchMultiCommit(select)
          }).catch(() => {})
        } else {
          this.doCreatePatchMultiCommit(select)
        }
      })
    },
    doCreatePatchMultiCommit(select) {
      this.input.commitIds = []
      for (let i = 0; i < select.length; i++) {
        this.input.commitIds.push(select[i].commitId)
      }
      this.fullscreenLoading = true
      git.changeFilesV2(this.input).then(res => {
        this.changeFilesDialog.data = res.data
        this.changeFilesDialog.title = this.input.commitIds.length + ' 个提交记录的差异'
        this.changeFilesDialog.show = true
        this.changeFilesDialog.patchMethod = git.createPatchV2
        this.fullscreenLoading = false
      }).catch(res => {
        this.fullscreenLoading = false
      })
    }
  }
}
</script>

<style scoped>
  @import "../../assets/custom-theme/bootstrap.css";

  /deep/ .custom-tree-node{
    display: flex !important;
    justify-content: space-between;
    align-items: center;
    display: block;
    width: 100%;
    padding: 0 10px 0 2px;
  }

  /deep/.el-table .error-row {
    color: orangered;
  }

</style>
